/* -*- C++ -*- */

//=============================================================================
/*
 * @author Feloweria <380374483@qq.com>
 * Copyright (C) Feloweria
 * 
 * $ID 2013-07-08 03:41:08 PM
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * @version 1.0
 */
//=============================================================================

FELOWRIA_BEGIN

template<typename Encode>
const typename StringConvertor<Encode>::Encode StringConvertor<Encode>::DIGIT_BEGIN = Encode('0');

template<typename Type>
const typename StringConvertor<Type>::Encode StringConvertor<Type>::DIGIT_END = Encode('9');

template<typename Type>
const typename StringConvertor<Type>::Encode StringConvertor<Type>::PLUS = Encode('+');

template<typename Type>
const typename StringConvertor<Type>::Encode StringConvertor<Type>::MINUTE = Encode('-');

template<typename Type>
const typename StringConvertor<Type>::Encode StringConvertor<Type>::DECIMAL_POINT = Encode('.');

template<typename Type>
const typename StringConvertor<Type>::String StringConvertor<Type>::TRUE_STRING[] = { "TRUE", "True", "true" };

template<typename Type>
const typename StringConvertor<Type>::String StringConvertor<Type>::FALSE_STRING[] = { "FALSE", "False", "false" };

template<typename Type>
const int StringConvertor<Type>::BOOL_NUM = 3;

#define STRING_CONVERT_TO_UINT_DEFINE(TYPE,NAME)	\
template<typename Type>	\
bool StringConvertor<Type>::Is##NAME(const String &string)	\
{	\
	int32 length = string.length();\
	static const int32 min = 1,max = sizeof(TYPE) * 3 ;\
	if(length > max || length < min)	\
		return false;	\
	for(const Encode *cur = string.c_str(),*end = cur + length;cur < end;++cur)	\
	{	\
		if(!IsDigit(*cur))\
			return false;	\
	}	\
	return true;	\
}	\
template<typename Type>	\
TYPE StringConvertor<Type>::To##NAME(const String &string)	\
{	\
	TYPE value = 0;\
	for(const Encode *cur = string.c_str(),*end = cur + string.length();cur < end;++cur)	\
			value = value * 10 + (*cur - DIGIT_BEGIN);	\
	return value;	\
}	\
template<typename Type>	\
bool StringConvertor<Type>::Is##NAME(const Encode *string)	\
{	\
	if(!string)	\
		return false; \
	if(!string[0])	\
		return false;	\
	static const int32 max = sizeof(TYPE) * 3;\
	for(const Encode *cur = string,*end = cur + max;*cur;++cur)	\
	{	\
		if(cur > end)	\
			return false;	\
		\
		if(!IsDigit(*cur))\
			return false;	\
	}	\
	return true;	\
}	\
template<typename Type>	\
TYPE StringConvertor<Type>::To##NAME(const Encode *string)	\
{	\
	TYPE value = 0;\
	for(const Encode *cur = string;*cur;++cur)	\
		value = value * 10 + (*cur - DIGIT_BEGIN);	\
	return value;	\
}	

	STRING_CONVERT_TO_UINT_DEFINE(uint8,UInt8)
	STRING_CONVERT_TO_UINT_DEFINE(uint16,UInt16)
	STRING_CONVERT_TO_UINT_DEFINE(uint32,UInt32)
	STRING_CONVERT_TO_UINT_DEFINE(uint64,UInt64)
	
#undef STRING_CONVERT_TO_UINT_DEFINE

#define STRING_CONVERT_TO_INT_DEFINE(TYPE,NAME)	\
template<typename Type>	\
bool StringConvertor<Type>::Is##NAME(const String &string)	\
{	\
	int32 length = string.length();\
	static const int32 min = 1,max = sizeof(TYPE) * 3 + 1;\
	if(length > max || length < min)	\
		return false;	\
	bool result = IsNegative(string[0]);		\
	for (const Encode *cur = string.c_str() + result * 1, *end = string.c_str() + length; cur < end; ++cur)	\
	{	\
		if(!IsDigit(*cur))\
			return false;	\
	}	\
	\
	return true;	\
}	\
template<typename Type>	\
TYPE StringConvertor<Type>::To##NAME(const String &string)	\
{	\
	TYPE value = 0;\
	bool result = IsNegative(string[0]);		\
	for (const Encode *cur = string.c_str() + result * 1, *end = string.c_str() + string.length(); cur < end; ++cur)	\
			value = value * 10 + (*cur - DIGIT_BEGIN);	\
	if(result)	\
		value = -value;	\
	\
	return value;	\
}	\
template<typename Type>	\
bool StringConvertor<Type>::Is##NAME(const Encode *string)	\
{	\
	static const int32 min = 1,max = sizeof(TYPE) * 3 + 1;\
	bool result = IsNegative(string[0]);		\
	for(const Encode *cur = string + result * 1,*end = cur + max;*cur;++cur)	\
	{	\
		if(cur > end)\
			return false;	\
		if(!IsDigit(*cur))	\
			return false;	\
	}	\
	\
	return true;	\
}	\
template<typename Type>	\
TYPE StringConvertor<Type>::To##NAME(const Encode *string)	\
{	\
	TYPE value = 0;\
	bool result = IsNegative(string[0]);		\
	for(const Encode *cur = string + result * 1;*cur;++cur)	\
			value = value * 10 + (*cur - DIGIT_BEGIN);	\
	if(result)	\
		value = -value;	\
	\
	return value;	\
}	

	STRING_CONVERT_TO_INT_DEFINE(int8,Int8)
	STRING_CONVERT_TO_INT_DEFINE(int16,Int16)
	STRING_CONVERT_TO_INT_DEFINE(int32,Int32)
	STRING_CONVERT_TO_INT_DEFINE(int64,Int64)
	
#undef STRING_CONVERT_TO_INT_DEFINE
	
template<typename Type>
inline bool StringConvertor<Type>::IsDigit(const Encode &encode)
{
	if(encode > DIGIT_END || encode < DIGIT_BEGIN)
		return false;
	
	return true;
}

template<typename Type>
inline bool StringConvertor<Type>::IsNegative(const Encode &encode)
{	
	return encode == MINUTE;
}

template<typename Type>
inline bool StringConvertor<Type>::IsDemicalPoint(const Encode &encode)
{	
	return encode == DECIMAL_POINT;
}

#define STRING_CONVERT_TO_FLOAT_DEFINE(TYPE,NAME)	\
template<typename Type>	\
bool	StringConvertor<Type>::Is##NAME(const Encode *string)\
{\
	bool result = IsNegative(string[0]); \
	\
	for (const Encode *cur = string + result * 1; *cur; ++cur)\
{\
	if (!IsDigit(*cur) && !IsDemicalPoint(*cur))\
	return false; \
}\
	\
	return true; \
}\
template<typename Type>\
bool	StringConvertor<Type>::Is##NAME(const String &string)\
{\
	bool result = IsNegative(string[0]); \
	\
	for (const Encode *cur = string.c_str() + result * 1, *end = string.c_str() + string.length(); cur < end; ++cur)\
	{\
		if (!IsDigit(*cur) && !IsDemicalPoint(*cur))\
			return false; \
	}\
	\
	return true; \
}\
template<typename Type>\
TYPE	StringConvertor<Type>::To##NAME(const Encode *string)\
{\
	TYPE value = 0; \
	TYPE demical = 0; \
	bool result = IsNegative(string[0]); \
	int32 loop_time = 0; \
	int32 demical_time = 0; \
	const Encode *cur = string + result * 1;\
	while(*cur)\
	{\
		if (IsDemicalPoint(*cur))\
		{\
			cur++;\
			break; \
		}\
		\
		if (loop_time > 10)\
			value = value * 10; \
		else\
			value = value * 10 + (*cur - DIGIT_BEGIN); \
		\
		++cur, ++loop_time;\
	}\
	while (*cur)\
	{\
		if(loop_time > 10)\
		{\
			if(demical_time > 0)\
			{\
				if ((*cur - DIGIT_BEGIN) > 5)\
					++demical;\
			}else\
			{\
				if ((*cur - DIGIT_BEGIN) > 5)\
					++value;\
			}\
			break; \
		}\
		if (demical_time > 8)\
		{\
			if (*cur - DIGIT_BEGIN > 5)\
				++demical;\
			break; \
		}\
		++demical_time; \
		\
		demical = demical * 10 + (*cur - DIGIT_BEGIN); \
		\
		++cur, ++loop_time;\
	}\
	\
	if (result)	\
		value = -value;	\
	\
	while (demical_time--)\
		demical = demical / 10.0; \
	\
	return value + demical; \
}\
template<typename Type>\
TYPE	StringConvertor<Type>::To##NAME(const String& string)\
{\
	TYPE value = 0; \
	TYPE demical = 0; \
	bool result = IsNegative(string[0]); \
	int32 loop_time = 0; \
	int32 demical_time = 0; \
	const Encode *cur = string.c_str() + result * 1;\
	while(*cur)\
	{\
		if (IsDemicalPoint(*cur))\
		{\
			cur++;\
			break; \
		}\
		\
		if (loop_time > 10)\
			value = value * 10; \
		else\
			value = value * 10 + (*cur - DIGIT_BEGIN); \
		\
		++cur, ++loop_time;\
	}\
	while (*cur)\
	{\
		if(loop_time > 10)\
		{\
			if(demical_time > 0)\
			{\
				if ((*cur - DIGIT_BEGIN) > 5)\
					++demical;\
			}else\
			{\
				if ((*cur - DIGIT_BEGIN) > 5)\
					++value;\
			}\
			\
			break; \
		}\
		if (demical_time > 8)\
		{\
			if (*cur - DIGIT_BEGIN > 5)\
				++demical;\
			break; \
		}\
		++demical_time; \
		\
		demical = demical * 10 + (*cur - DIGIT_BEGIN); \
		\
		++cur, ++loop_time;\
	}\
	\
	if (result)	\
		value = -value;	\
	\
	while (demical_time--)\
		demical = demical / 10.0; \
	\
	return value + demical; \
}

template<typename Type>
bool	StringConvertor<Type>::IsBool(const String &string)
{
	for (int32 i = 0; i < BOOL_NUM; ++i)
		if(TRUE_STRING[i] == string || FALSE_STRING[i] == string)
			return true;
		
	return false;
}

template<typename Type>
bool	StringConvertor<Type>::IsBool(const Encode *string)
{
	for (int32 i = 0; i < BOOL_NUM; ++i)
		if(TRUE_STRING[i] == string || FALSE_STRING[i] == string)
			return true;
		
	return false;
}

template<typename Type>
bool	StringConvertor<Type>::ToBool(const Encode *string)
{
	if(!IsBool(string))
		return false;

	for (int32 i = 0; i < BOOL_NUM; ++i)
	{
		if(TRUE_STRING[i] == string)
			return true;
		
		if(FALSE_STRING[i] == string)
			return false;
	}
	
	return false;
}


	STRING_CONVERT_TO_FLOAT_DEFINE(float,Float)
	STRING_CONVERT_TO_FLOAT_DEFINE(double,Double)

#undef STRING_CONVERT_TO_FLOAT_DEFINE

template<typename Type>
bool	StringConvertor<Type>::ToBool(const String &string)
{
	if(!IsBool(string))
		return false;
	
	
	for(int32 i = 0;i < BOOL_NUM;++i)
	{
		if(TRUE_STRING[i] == string)
			return true;
		
		if(FALSE_STRING[i] == string)
			return false;
	}
	
	return false;
}
#define UINT_CONVERT_TO_STRING_DEFINE(TYPE,NAME)	\
template<typename Type>\
typename StringConvertor<Type>::Encode*		StringConvertor<Type>::ToString(Encode *buf, int32 size, const TYPE value)\
{\
	if(size <= 1)\
	    return NULL;\
	TYPE v = value;\
	Encode *cur = buf + size; \
	*--cur = 0;\
	\
	do\
	{\
		if(cur == buf)\
		    return NULL; \
		*--cur = v % 10 + DIGIT_BEGIN; \
		v = v / 10; \
	}while(v); \
	\
	return cur; \
}\
template<typename Type>\
typename StringConvertor<Type>::String		StringConvertor<Type>::ToString(const TYPE value)\
{\
	static const int SIZE = 32;\
	Encode buf[SIZE];\
	\
	Encode *result = ToString(buf, SIZE, value);\
	return result;\
}	

	UINT_CONVERT_TO_STRING_DEFINE(uint8, UInt8)
	UINT_CONVERT_TO_STRING_DEFINE(uint16, UInt16)
	UINT_CONVERT_TO_STRING_DEFINE(uint32, UInt32)
	UINT_CONVERT_TO_STRING_DEFINE(uint64, UInt64)


#define INT_CONVERT_TO_STRING_DEFINE(TYPE,NAME)		\
template<typename Type>\
typename StringConvertor<Type>::Encode*		StringConvertor<Type>::ToString(Encode *buf, int32 size, const TYPE value)\
{\
	if(size <= 1)\
		return NULL;\
	TYPE v = value;\
	\
	Encode *cur = buf + size; \
	*--cur = 0; \
	\
	bool isNegative = v < 0;\
	do\
	{\
		if(cur == buf)\
			return NULL; \
		*--cur = v % 10 + DIGIT_BEGIN; \
		v = v / 10; \
	}while(v); \
	\
	if (isNegative)\
	{\
		if(cur == buf)\
		    return NULL; \
		\
		*--cur = MINUTE;\
	}\
	\
	return cur; \
}\
template<typename Type>\
typename StringConvertor<Type>::String		StringConvertor<Type>::ToString(const TYPE value)\
{\
	static const int SIZE = 32; \
	Encode buf[SIZE]; \
	\
	Encode *result = ToString(buf, SIZE, value); \
	return result; \
}
	UINT_CONVERT_TO_STRING_DEFINE(int8, Int8)
	UINT_CONVERT_TO_STRING_DEFINE(int16, Int16)
	UINT_CONVERT_TO_STRING_DEFINE(int32, Int32)
	UINT_CONVERT_TO_STRING_DEFINE(int64, Int64)

#define FLOAT_CONVERT_TO_STRING_DEFINE(TYPE,NAME)		\
template<typename Type>\
typename StringConvertor<Type>::Encode*		StringConvertor<Type>::ToString(Encode *buf, int32 size, const TYPE value)\
{\
	if(size <= 1)\
		return NULL;\
	\
	const static int32 time = 100000000; \
	int decimal_time = 8;\
	int32 interger = int32(value);\
	int32 decimal = 0;\
	bool isNegative = interger < 0; \
	\
	Encode* cur = buf + size;\
	*--cur = 0;\
	if (isNegative)\
	{\
		decimal = int32(-(value - interger) * time + 0.5); \
		interger = -interger;\
	}else\
	{\
		decimal = int32((value - interger) * time + 0.5); \
	}\
	\
	while (decimal && !(decimal % 10) && decimal_time--)\
		decimal = decimal / 10; \
	\
	while (decimal_time--)\
	{\
		if(cur == buf)\
			return NULL;\
		*--cur = decimal % 10 + DIGIT_BEGIN; \
		decimal = decimal / 10; \
	}\
	if(*cur != 0)\
		*--cur = '.';\
	\
	do\
	{\
		if(cur == buf)\
			return NULL;\
		*--cur = (interger % 10) + '0';\
		interger /= 10;\
	} while (interger);\
	\
	if (isNegative)\
	{\
		if(cur == buf)\
			return NULL;\
		*--cur = '-';\
	}\
	\
	return cur;\
}\
template<typename Type>\
typename StringConvertor<Type>::String		StringConvertor<Type>::ToString(const TYPE value)\
{\
	static const int SIZE = 32; \
	Encode buf[SIZE]; \
	\
	Encode *result = ToString(buf, SIZE, value); \
	return result; \
}
	FLOAT_CONVERT_TO_STRING_DEFINE(float, Float)
	FLOAT_CONVERT_TO_STRING_DEFINE(double, Double)

template<typename Type>
typename StringConvertor<Type>::String		StringConvertor<Type>::ToString(const bool value)
{
	if (value)
		return TRUE_STRING[0];

	return FALSE_STRING[0];
}

template<typename Type>
typename StringConvertor<Type>::Encode*		StringConvertor<Type>::ToString(Encode *buf, int32 size, const bool value)
{
	if (size < TRUE_STRING[0] || size < FALSE_STRING[0])
		return NULL;

	if (value)
		strcpy(buf, TRUE_STRING[0].c_str());
	else
		strcpy(buf, FALSE_STRING[0].c_str());

	return buf;
}

FELOWRIA_END